﻿using System.Net.Sockets;
using System.Net;
using System.Text.RegularExpressions;
using System.Collections;
using System.Configuration;
using System.Diagnostics;
using LiveCharts.Wpf;
using System.Windows.Forms;
using SunnyUI.Net;
using DBUtil.Net;

namespace JFBG
{
    public partial class MainForm : UIHeaderMainFrame
    {
        //监听线程
        public static Thread receiveThread;
        //服务器套接字
        public static Socket serverSocket;
        //服务器端口
        public static EndPoint adEndPoint;
        //是否打开了服务端口
        public static bool isOpenServerPort;

        public static DBAccess db;

        public double waveBeginValue;

        public int waveInterval;

        public int waveDataPoints;

        public int waveChannelCount;

        public int waveRetDataRate;

        public MainForm()
        {
            InitializeComponent();

            DBUtil.Net.DBFactory.AddDBSupport<DBUtil.Net.Provider.MySql.MySqlDBFactory>();
            db = DBFactory.CreateDB(DBType.MYSQL, "Server=127.0.0.1;Database=jfbg;Uid=root;Pwd=123456;AllowLoadLocalInfile=true;SslMode=none;AllowPublicKeyRetrieval=True;Charset=utf8mb4;", 
                DBSetting.NewInstance().SetSqlMonitor(arg =>
                {
                    Console.WriteLine(arg);
                    return Task.CompletedTask;
                }));
            //准备数据
            //db.ExecuteSql(db.Manage.DropTableIfExistSql("raster"));
            //db.ExecuteSql("create table raster(id bigint primary key, channel_id int, raster_count int, collect_time datetime, wave1_temp double(10, 4), wave1_flex double(10, 4), flex1_value double(10, 4), wave2_temp double(10, 4), wave2_flex double(10, 4), flex2_value double(10, 4), stress_value double(10, 4), axial_value double(10, 4))");

            //db.ExecuteSql(
            //db.Insert("raster")
            //.SetColumn("channel_id", 1)
            //.SetColumn("raster_count", 1)
            //.SetColumn("collect_time", DateTime.Now)
            //.SetColumn("wave1_temp", 1.001)
            //.SetColumn("wave1_flex", 1.001)
            //.SetColumn("flex1_value", 1.001)
            //.SetColumn("wave2_temp", 1.001)
            //.SetColumn("wave2_flex", 1.001)
            //.SetColumn("flex2_value", 1.001)
            //.SetColumn("stress_value", 1.001)
            //.SetColumn("axial_value", 1.001)
            //.ToSql());

            //设置关联
            Header.TabControl = MainTabControl;

            //增加页面到Main
            AddPage(new Page1(), 1001);
            AddPage(new Page2(), 1002);
            AddPage(new Page3(), 1003);
            AddPage(new Page4(), 1004);
            AddPage(new Page5(), 1005);
            //设置Header节点索引
            Header.SetNodePageIndex(Header.Nodes[0], 1001);
            Header.SetNodePageIndex(Header.Nodes[1], 1002);
            Header.SetNodePageIndex(Header.Nodes[2], 1003);
            Header.SetNodePageIndex(Header.Nodes[3], 1004);
            Header.SetNodePageIndex(Header.Nodes[4], 1005);
            //显示默认界面
            Header.SelectedIndex = 0;

            InitIntfaceData();
            //开启接收消息线程
            //receiveThread = new Thread(ReciveMessage);
            //receiveThread.Start();
        }

        private void InitIntfaceData()
        {
            //得到主机名
            string HostName = Dns.GetHostName();
            //通过主机名获取IP
            IPHostEntry IpEntry = Dns.GetHostEntry(HostName);
            //可变数组
            ArrayList addressList = new ArrayList();

            addressList.Add("0.0.0.0");
            addressList.Add("127.0.0.1");

            for (int i = 0; i < IpEntry.AddressList.Length; i++)
            {
                //从IP地址列表中筛选出IPv4类型的IP地址
                //AddressFamily.InterNetwork表示此IP为IPv4,
                //AddressFamily.InterNetworkV6表示此地址为IPv6类型
                if (IpEntry.AddressList[i].AddressFamily == AddressFamily.InterNetwork)
                {
                    addressList.Add(IpEntry.AddressList[i].ToString());
                }
            }
            int selectedIndex = 0;
            string myAddress = ConfigurationManager.AppSettings["cbMyAddress"];
            //固定大小
            addressList.TrimToSize();
            object[] adList = new object[addressList.Count];
            for (int i = 0; i < addressList.Count; i++)
            {
                adList[i] = addressList[i];
                if (myAddress.Equals(adList[i]))
                {
                    selectedIndex = i;
                }
            }
            this.cbMyAddress.Items.AddRange(adList);
            this.cbMyAddress.SelectedIndex = selectedIndex;
            this.tbMyPort.Text = ConfigurationManager.AppSettings["tbMyPort"];
            this.tbAbverseIp.Text = ConfigurationManager.AppSettings["tbAbverseIp"];
            this.tbAbversePort.Text = ConfigurationManager.AppSettings["tbAbversePort"];
            this.tbWaveBeginValue.Text = ConfigurationManager.AppSettings["tbWaveBeginValue"];
            this.tbWaveInterval.Text = ConfigurationManager.AppSettings["tbWaveInterval"];
            this.tbWaveChannelCount.Text = ConfigurationManager.AppSettings["tbWaveChannelCount"];
            this.tbWaveDataPoints.Text = ConfigurationManager.AppSettings["tbWaveDataPoints"];
            this.tbWaveRetDataRate.Text = ConfigurationManager.AppSettings["tbWaveRetDataRate"];
        }

        public static Socket getServerSocket()
        {
            return serverSocket;
        }

        public static EndPoint getEndPoint()
        {
            return adEndPoint;
        }

        public static bool getOpenServerPort()
        {
            return isOpenServerPort;
        }

        //根据字符串获取端口
        public static int getPort(string str)
        {
            if (!IsPort(str))
            {
                //不是端口
                return -1;
            }
            //转换成整型
            int port = Convert.ToInt32(str);
            if (port >= 0 && port <= 65535)
            {
                //如果是合法端口
                return port;
            }
            else
            {//不是合法端口
                return -1;
            }
        }

        //根据字符串获取IP地址
        public static string getIPAddress(string str)
        {
            if (!IsIP(str))
            {
                //如果不是IP
                if (IsDomain(str))
                {
                    //如果是域名
                    try
                    {
                        //解析域名
                        IPAddress[] host = Dns.GetHostAddresses(str);
                        //域名解析的IP地址
                        IPAddress ipAddress = host[0];
                        //改成IP地址
                        str = ipAddress.ToString();
                    }
                    catch
                    {
                        return "";
                    }
                }
                else
                {
                    return "";
                }
            }
            //返回IP地址
            return str;
        }

        // 验证字符串是否是域名
        public static bool IsDomain(string str)
        {
            string pattern = @"^(?=^.{3,255}$)[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+$";
            return IsMatch(pattern, str);
        }

        // 验证字符串是否是IP
        public static bool IsIP(string str)
        {
            string pattern = @"(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)\.(25[0-5]|2[0-4]\d|[0-1]\d{2}|[1-9]?\d)";
            return IsMatch(pattern, str);
        }

        //判断是否为0-65535的数字
        public static bool IsPort(string str)
        {
            string pattern = @"^([0-9]|[1-9]\d|[1-9]\d{2}|[1-9]\d{3}|[1-5]\d{4}|6[0-4]\d{3}|65[0-4]\d{2}|655[0-2]\d|6553[0-5])$";
            return IsMatch(pattern, str);
        }

        // 判断一个字符串，是否匹配指定的表达式(区分大小写的情况下)
        public static bool IsMatch(string expression, string str)
        {
            Regex reg = new Regex(expression);
            if (string.IsNullOrEmpty(str))
            {
                return false;
            }
            return reg.IsMatch(str);
        }

        public static decimal DivideAndRound(decimal dividend, decimal divisor, int decimalPlaces)
        {
            if (divisor == 0)
            {
                throw new DivideByZeroException();
            }
            decimal result = dividend / divisor;
            return Math.Round(result, decimalPlaces);
        }

        
        private void ReciveData(byte[] revData)
        {
            byte head = revData[0];
            byte cmd = revData[1];

            if (cmd == 0x02)
            {

            }
            else if (cmd == 0x04)
            {

            }
            else if (cmd == 0x06)
            {

            }
            else if (cmd == 0x07)
            {

            }
            else if (cmd == 0x08)
            {

            }
            else if (cmd == 0x0A)
            {

            }
            else if (cmd == 0x0C)
            {

            }
            else if (cmd == 0x14)
            {

            }
            else if (cmd == 0x16)
            {

            }
            else if (cmd == 0x17)
            {
                if(revData.Length < 3){ return; }
                byte valueL1 = revData[2];
                if (revData.Length < 4) { return; }
                byte valueH1 = revData[3];
                this.waveBeginValue = Math.Round(Convert.ToDouble(DivideAndRound((valueL1 + valueH1 * 256), 1000, 5) + 1520), 4) ;
                if (revData.Length < 5) { return; }
                byte valueL2 = revData[4];
                if (revData.Length < 6) { return; }
                byte valueH2 = revData[5];
                this.waveInterval = Convert.ToInt32(valueL2 + valueH2 * 256);
                if (revData.Length < 7) { return; }
                byte valueL3 = revData[6];
                if (revData.Length < 8) { return; }
                byte valueH3 = revData[7];
                this.waveDataPoints = Convert.ToInt32(valueL3 + valueH3 * 256);
                if (revData.Length < 9) { return; }
                byte valueL4 = revData[8];
                if (revData.Length < 10) { return; }
                byte valueH4 = revData[9];
                this.waveChannelCount = Convert.ToInt32(valueL4 + valueH4 * 256);
                if (revData.Length < 11) { return; }
                byte valueL5 = revData[10];
                if (revData.Length < 12) { return; }
                byte valueH5 = revData[11];
                this.waveRetDataRate = Convert.ToInt32(valueL5 + valueH5 * 256);

                if (this.tbWaveBeginValue.InvokeRequired)
                {
                    this.tbWaveBeginValue.Invoke(new Action(() =>
                    {
                        this.tbWaveBeginValue.Text = this.waveBeginValue + "";
                    }));
                }
                else
                {
                    this.tbWaveBeginValue.Text = this.waveBeginValue + "";
                }

                if (this.tbWaveInterval.InvokeRequired)
                {
                    this.tbWaveInterval.Invoke(new Action(() =>
                    {
                        this.tbWaveInterval.Text = this.waveInterval + "";
                    }));
                }
                else
                {
                    this.tbWaveInterval.Text = this.waveInterval + "";
                }

                if (this.tbWaveDataPoints.InvokeRequired)
                {
                    this.tbWaveDataPoints.Invoke(new Action(() =>
                    {
                        this.tbWaveDataPoints.Text = this.waveDataPoints + "";
                    }));
                }
                else
                {
                    this.tbWaveDataPoints.Text = this.waveDataPoints + "";
                }

                if (this.tbWaveChannelCount.InvokeRequired)
                {
                    this.tbWaveChannelCount.Invoke(new Action(() =>
                    {
                        this.tbWaveChannelCount.Text = this.waveChannelCount + "";
                    }));
                }
                else
                {
                    this.tbWaveChannelCount.Text = this.waveChannelCount + "";
                }

                if (this.tbWaveRetDataRate.InvokeRequired)
                {
                    this.tbWaveRetDataRate.Invoke(new Action(() =>
                    {
                        this.tbWaveRetDataRate.Text = this.waveRetDataRate + "";
                    }));
                }
                else
                {
                    this.tbWaveRetDataRate.Text = this.waveRetDataRate + "";
                }

                Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
                AppSettingsSection app = config.AppSettings;
                app.Settings["tbWaveBeginValue"].Value = this.waveBeginValue + "";
                app.Settings["tbWaveInterval"].Value = this.waveInterval + "";
                app.Settings["tbWaveDataPoints"].Value = this.waveDataPoints + "";
                app.Settings["tbWaveChannelCount"].Value = this.waveChannelCount + "";
                app.Settings["tbWaveRetDataRate"].Value = this.waveRetDataRate + "";
                config.Save(ConfigurationSaveMode.Modified);
            }
            else if (cmd == 0x24)
            {

            }
            else if (cmd == 0x26)
            {
            }
            else if (cmd == 0x2E)
            {

            }
            else if (cmd == 0x30)
            {
            }
            else if (cmd == 0x32)
            {

            }
            else if (cmd == 0x34)
            {

            }
            else
            {

            }
        }
        

        // 接收发送给本机IP对应端口号的数据报
        private void ReciveMessage()
        {
            Socket serverSocket = MainForm.getServerSocket();
            if (serverSocket == null){
                return;
            }
            try
            {
                while (MainForm.getOpenServerPort())
                {
                    //用来保存发送方的IP和端口号
                    EndPoint point = new IPEndPoint(IPAddress.Any, 0);
                    //消息缓存区申请
                    byte[] buffer = new byte[512];
                    //接收数据报
                    int length = serverSocket.ReceiveFrom(buffer, ref point);
                    byte[] revBuf = new byte[length];
                    Buffer.BlockCopy(buffer, 0, revBuf, 0, length);
                    //显示在视图里
                    this.ReciveData(revBuf);
                }
            }
            catch (SocketException e)
            {
                //MessageBox.Show("接收发送给本机IP对应端口号的数据报错！" + e.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            finally
            {
                //if (serverSocket != null)
                //{
                //    if (serverSocket.Connected)
                //    {
                //        serverSocket.Disconnect(false);
                //    }
                //    serverSocket.Close();
                //    serverSocket.Dispose();
                //}
            }
        }
        
        private void btnOpenServer_Click(object sender, System.EventArgs e)
        {
            //停用按钮，防止多次点击
            this.btnOpenServer.Enabled = false;
            //如果服务是打开的
            if (isOpenServerPort)
            {
                try
                {
                    //如果套接字不为空
                    if (serverSocket != null)
                    {
                        if (serverSocket.Connected)
                        {
                            serverSocket.Disconnect(false);
                        }
                        serverSocket.Close();
                        serverSocket.Dispose();
                    }
                    if (receiveThread != null)
                    {
                        receiveThread.Interrupt();
                    }
                }
                catch (Exception ex)
                {
                    MessageBox.Show("接收发送给本机IP对应端口号的数据报错！" + ex.Message, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {

                }

                //设置服务为关闭状态
                isOpenServerPort = false;
                //设置界面为服务关闭状态
                this.lbServerState.Text = "服务器已关闭";
                this.lbServerState.ForeColor = System.Drawing.Color.Blue;
                this.btnOpenServer.Text = "打开服务端口";
                //UI显示
                this.cbMyAddress.Enabled = true;
                this.tbMyPort.Enabled = true;
                this.tbAbverseIp.Enabled = true;
                this.tbAbversePort.Enabled = true;
            }
            else
            {
                //获取地址
                string myIp = getIPAddress(cbMyAddress.Text);
                if (myIp == null)
                {
                    MessageBox.Show("服务器地址不正确，请输入IP或者域名！\n域名需要有DNS服务器！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.btnOpenServer.Enabled = true;
                    return;
                }
                int myPort = getPort(tbMyPort.Text);
                if (myPort == -1)
                {
                    MessageBox.Show("服务器端口格式不对！（值：0 - 65535）", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.btnOpenServer.Enabled = true;
                    return;
                }
                try
                {
                    //创建套接字，以UDP的方式
                    serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                    //设置好地址
                    EndPoint  myEndPoint = new IPEndPoint(IPAddress.Parse(myIp), myPort);
                    //绑定端口号和IP
                    serverSocket.Bind(myEndPoint);
                }
                catch (SocketException es)
                {
                    //出现异常
                    MessageBox.Show("绑定端口时出现异常：" + es.ErrorCode + "！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    //按钮启用
                    btnOpenServer.Enabled = true;
                }

                //获取地址
                string adIp = getIPAddress(this.tbAbverseIp.Text);
                if (adIp == null)
                {
                    MessageBox.Show("对方主机地址不正确，请输入IP或者域名！\n域名需要有DNS服务器！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.btnOpenServer.Enabled = true;
                    return;
                }
                //对方端口
                int adPort = getPort(this.tbAbversePort.Text);
                if (adPort == -1)
                {
                    MessageBox.Show("对方主机端口格式不对！（值：0 - 65535）", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    this.btnOpenServer.Enabled = true;
                    return;
                }

                //设置好地址
                adEndPoint = new IPEndPoint(IPAddress.Parse(adIp), adPort);


                //如果打开了并且绑定端口了
                if (serverSocket != null && serverSocket.IsBound)
                {
                    //设置服务为打开状态
                    isOpenServerPort = true;
                    //设置界面为服务打开状态
                    this.lbServerState.Text = "服务器已开启";
                    this.lbServerState.ForeColor = System.Drawing.Color.Red;
                    this.btnOpenServer.Text = "关闭服务端口";
                    //UI显示
                    this.cbMyAddress.Enabled = false;
                    this.tbMyPort.Enabled = false;
                    this.tbAbverseIp.Enabled = false;
                    this.tbAbversePort.Enabled = false;
                    
                    try
                    {
                        //如果不为空
                        byte[] bmsg = [0x01, 0x17];
                        if (bmsg != null)
                        {
                            //开启接收消息线程
                            receiveThread = new Thread(ReciveMessage);
                            receiveThread.Start();

                            //发送数据包
                            serverSocket.SendTo(bmsg, adEndPoint);
                        }
                        else
                        {
                            MessageBox.Show("发送数据格式错误：" + bmsg, "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                        }
                    }
                    catch (SocketException es)
                    {
                        MessageBox.Show("发送数据报时出现异常：" + es.ErrorCode + "！", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }
                    finally
                    {

                    }
                }
            }
            this.btnOpenServer.Enabled = true;
        }

        private void MainForm_Load(object sender, EventArgs e)
        {

        }

        //窗口关闭事件委托，在窗口关闭事件前处理
        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (serverSocket != null)
            {
                if (serverSocket.Connected)
                {
                    serverSocket.Disconnect(false);
                }
                serverSocket.Close();
                serverSocket.Dispose();
            }
            if (receiveThread != null)
            {
                receiveThread.Interrupt();
            }
        }

        private void cbMyAddress_SelectedIndexChanged(object sender, EventArgs e)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            AppSettingsSection app = config.AppSettings;
            app.Settings["cbMyAddress"].Value = cbMyAddress.Text;
            config.Save(ConfigurationSaveMode.Modified);
        }

        private void tbMyPort_TextChanged(object sender, EventArgs e)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            AppSettingsSection app = config.AppSettings;
            app.Settings["tbMyPort"].Value = tbMyPort.Text;
            config.Save(ConfigurationSaveMode.Modified);
        }

        private void tbAbverseIp_TextChanged(object sender, EventArgs e)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            AppSettingsSection app = config.AppSettings;
            app.Settings["tbAbverseIp"].Value = tbAbverseIp.Text;
            config.Save(ConfigurationSaveMode.Modified);
        }

        private void tbAbversePort_TextChanged(object sender, EventArgs e)
        {
            Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            AppSettingsSection app = config.AppSettings;
            app.Settings["tbAbversePort"].Value = tbAbversePort.Text;
            config.Save(ConfigurationSaveMode.Modified);
        }
    }
}